﻿namespace SimpleWebServices.Data
{
    using System;
    using System.Data;
    using SimpleWebServices;
    using Xunit;

    public sealed class DataTableExtensionMethodsFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(typeof(DataTableExtensionMethods).IsStatic());
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableNull_bool()
        {
            Assert.Throws<ArgumentNullException>(() => (null as DataTable).ToCommaSeparatedValues(true));
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableEmpty_bool()
        {
            string expected = string.Empty;
            string actual = new DataTable().ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumn_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected = string.Empty;
            string actual = table.ToCommaSeparatedValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumn_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected = "column" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumnComma_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("col,umn", typeof(string));

            string expected = "\"col,umn\"" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumnQuotation_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("col\"umn", typeof(string));

            string expected = "col\"\"umn" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumns_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = string.Empty;
            string actual = table.ToCommaSeparatedValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableColumns_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = "column1,column2" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableRows()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            DataRow row = table.NewRow();
            row["column1"] = "row1-column1";
            row["column2"] = "row1-column2";
            table.Rows.Add(row);

            string expected = "column1,column2" + Environment.NewLine + "row1-column1,row1-column2" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableRowsStringNull()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));
            table.Columns.Add("column3", typeof(string));

            DataRow row = table.NewRow();
            row["column1"] = "row1-column1";
            row["column2"] = null as string;
            row["column3"] = "row1-column3";
            table.Rows.Add(row);

            string expected = "column1,column2,column3" + Environment.NewLine + "row1-column1,,row1-column3" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToCommaSeparatedValues_DataTableRowsDateTime()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(DateTime));

            DataRow row = table.NewRow();
            row["column1"] = new DateTime(1999, 12, 31);
            table.Rows.Add(row);

            string expected = "column1" + Environment.NewLine + "1999-12-31T00:00:00Z" + Environment.NewLine;
            string actual = table.ToCommaSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableNull_bool()
        {
            Assert.Throws<ArgumentNullException>(() => (null as DataTable).ToFixedWidthValues(true));
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableEmpty_bool()
        {
            string expected = string.Empty;
            string actual = new DataTable().ToFixedWidthValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableColumn_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected = string.Empty;
            string actual = table.ToFixedWidthValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableColumn_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected =
                "column" + Environment.NewLine +
                "------" + Environment.NewLine;
            string actual = table.ToFixedWidthValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableColumns_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = string.Empty;
            string actual = table.ToFixedWidthValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableColumns_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = 
                "column1 column2" + Environment.NewLine + 
                "------- -------" + Environment.NewLine;
            string actual = table.ToFixedWidthValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableRows()
        {
            DataTable table = new DataTable();
            table.Columns.Add("1", typeof(string));
            table.Columns.Add("2", typeof(string));

            DataRow row = table.NewRow();
            row["1"] = null as string;
            row["2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = string.Empty;
            row["2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "a";
            row["2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "ab";
            row["2"] = "ab";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "abc";
            row["2"] = "a";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "abc";
            row["2"] = string.Empty;
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "abc";
            row["2"] = null as string;
            table.Rows.Add(row);

            string expected =
                "1   2  " + Environment.NewLine +
                "--- ---" + Environment.NewLine +
                "    abc" + Environment.NewLine +
                "    abc" + Environment.NewLine +
                "a   abc" + Environment.NewLine +
                "ab  ab " + Environment.NewLine +
                "abc a  " + Environment.NewLine +
                "abc    " + Environment.NewLine +
                "abc    " + Environment.NewLine;
            string actual = table.ToFixedWidthValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToFixedWidthValues_DataTableRowsDateTime()
        {
            DateTime date = new DateTime(1999, 12, 31);

            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(DateTime));

            DataRow row = table.NewRow();
            row["column1"] = date;
            table.Rows.Add(row);

            string expected =
                "column1             " + Environment.NewLine +
                "--------------------" + Environment.NewLine + 
                date.ToXmlString() + Environment.NewLine;
            string actual = table.ToFixedWidthValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableNull_bool()
        {
            Assert.Throws<ArgumentNullException>(() => (null as DataTable).ToHtmlTable(true));
        }

        [Fact]
        public void op_ToHtmlTable_DataTableEmpty_bool()
        {
            string expected = string.Empty;
            string actual = new DataTable().ToHtmlTable(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableColumn_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected =
                "<table>" + Environment.NewLine + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableColumn_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected =
                "<table>" + Environment.NewLine +
                    "<thead>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<th>column</th>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</thead>" + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableColumns_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected =
                "<table>" + Environment.NewLine + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableColumns_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = 
                "<table>" + Environment.NewLine +
                    "<thead>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<th>column1</th>" +
                            "<th>column2</th>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</thead>" + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableRows()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            DataRow row = table.NewRow();
            row["column1"] = null as string;
            row["column2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["column1"] = string.Empty;
            row["column2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["column1"] = "a";
            row["column2"] = "abc";
            table.Rows.Add(row);

            string expected = 
                "<table>" + Environment.NewLine +
                    "<thead>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<th>column1</th>" +
                            "<th>column2</th>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</thead>" +
                    "<tbody>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<td></td>" +
                            "<td>abc</td>" + Environment.NewLine +
                        "</tr>" +
                        "<tr>" + Environment.NewLine +
                            "<td></td>" +
                            "<td>abc</td>" + Environment.NewLine +
                        "</tr>" +
                        "<tr>" + Environment.NewLine +
                            "<td>a</td>" +
                            "<td>abc</td>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</tbody>" + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToHtmlTable_DataTableRowsDateTime()
        {
            DateTime date = new DateTime(1999, 12, 31);

            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(DateTime));

            DataRow row = table.NewRow();
            row["column1"] = date;
            table.Rows.Add(row);

            string expected =
                "<table>" + Environment.NewLine +
                    "<thead>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<th>column1</th>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</thead>" +
                    "<tbody>" + Environment.NewLine +
                        "<tr>" + Environment.NewLine +
                            "<td>" +
                            date.ToXmlString() +
                            "</td>" + Environment.NewLine +
                        "</tr>" + Environment.NewLine +
                    "</tbody>" + Environment.NewLine +
                "</table>";
            string actual = table.ToHtmlTable(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableNull_bool()
        {
            Assert.Throws<ArgumentNullException>(() => (null as DataTable).ToStringArray(true));
        }

        [Fact]
        public void op_ToStringArray_DataTableEmpty_bool()
        {
            string[,] expected = new string[0, 0];
            string[,] actual = new DataTable().ToStringArray(true);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableColumn_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string[,] expected = new string[0, 0];
            string[,] actual = table.ToStringArray(false);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableColumn_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string[,] expected = { { "column" } };
            string[,] actual = table.ToStringArray(true);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableColumns_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string[,] expected = new string[0, 0];
            string[,] actual = table.ToStringArray(false);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableColumns_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string[,] expected = { { "column1" }, { "column2" } };
            string[,] actual = table.ToStringArray(true);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableRows()
        {
            DataTable table = new DataTable();
            table.Columns.Add("1", typeof(string));
            table.Columns.Add("2", typeof(string));

            DataRow row = table.NewRow();
            row["1"] = null as string;
            row["2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = string.Empty;
            row["2"] = "abc";
            table.Rows.Add(row);

            row = table.NewRow();
            row["1"] = "a";
            row["2"] = "abc";
            table.Rows.Add(row);

            string[,] expected = new string[2, 4];
            expected[0, 0] = "1";
            expected[1, 0] = "2";
            expected[0, 1] = string.Empty;
            expected[1, 1] = "abc";
            expected[0, 2] = string.Empty;
            expected[1, 2] = "abc";
            expected[0, 3] = "a";
            expected[1, 3] = "abc";

            string[,] actual = table.ToStringArray(true);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToStringArray_DataTableRowsDateTime()
        {
            DateTime date = new DateTime(1999, 12, 31);

            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(DateTime));

            DataRow row = table.NewRow();
            row["column1"] = date;
            table.Rows.Add(row);

            string[,] expected = { { "column1" }, { date.ToXmlString() } };
            string[,] actual = table.ToStringArray(true);

            Assert.Equal<string[,]>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableNull_bool()
        {
            Assert.Throws<ArgumentNullException>(() => (null as DataTable).ToTabSeparatedValues(true));
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableEmpty_bool()
        {
            string expected = string.Empty;
            string actual = new DataTable().ToTabSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableColumn_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected = string.Empty;
            string actual = table.ToTabSeparatedValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableColumn_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column", typeof(string));

            string expected = "column" + Environment.NewLine;
            string actual = table.ToTabSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableColumns_boolFalse()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = string.Empty;
            string actual = table.ToTabSeparatedValues(false);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableColumns_boolTrue()
        {
            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(string));
            table.Columns.Add("column2", typeof(string));

            string expected = "column1\tcolumn2" + Environment.NewLine;
            string actual = table.ToTabSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableRows()
        {
            DataTable table = new DataTable();
            table.Columns.Add("1", typeof(string));
            table.Columns.Add("2", typeof(string));

            DataRow row = table.NewRow();
            row["1"] = string.Empty;
            row["2"] = "abc";
            table.Rows.Add(row);

            string expected =
                "1\t2" + Environment.NewLine +
                "\tabc" + Environment.NewLine;
            string actual = table.ToTabSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToTabSeparatedValues_DataTableRowsDateTime()
        {
            DateTime date = new DateTime(1999, 12, 31);

            DataTable table = new DataTable();
            table.Columns.Add("column1", typeof(DateTime));

            DataRow row = table.NewRow();
            row["column1"] = date;
            table.Rows.Add(row);

            string expected = "column1" + Environment.NewLine + date.ToXmlString() + Environment.NewLine;
            string actual = table.ToTabSeparatedValues(true);

            Assert.Equal<string>(expected, actual);
        }
    }
}